﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Systematize.Data.EntityFramework.Context;
using Systematize.Domain.Data;
using Systematize.Domain.Entities;

namespace Systematize.Data.EntityFramework
{
    public class RepositoryAsync<T> : Repository<T>, IRepositoryAsync<T>
        where T : Entity, ILibraryItem
    {
        private readonly IDbContextAsync _dbContextAsync;

        public RepositoryAsync(IDbContextAsync dbContextAsync)
            : base(dbContextAsync)
        {
            _dbContextAsync = dbContextAsync;
        }

        public async Task<int> CountAsync()
        {
            return await Entities.CountAsync();
        }

        public async Task<int> CountAsync(Expression<Func<T, bool>> predicate)
        {
            return await Entities.CountAsync(predicate);
        }

        public async Task<IEnumerable<T>> GetAllAsync()
        {
            return await Entities.ToListAsync();
        }

        public async Task<T> FindAsync(Expression<Func<T, bool>> predicate)
        {
            return await Entities.FirstOrDefaultAsync(predicate);
        }

        public async Task<IEnumerable<T>> FindAllAsync(Expression<Func<T, bool>> predicate)
        {
            return await Entities.Where(predicate).ToListAsync();
        }

        public async Task<int> InsertAsync(T entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");

            Entities.Add(entity);

            return await _dbContextAsync.SaveChangesAsync();
        }

        public async Task<int> UpdateAsync(T entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");

            var entry = _dbContext.Entry(entity);
            if (entry.State == EntityState.Detached)
            {
                Entities.Attach(entity);
                entry.State = EntityState.Modified;
            }

            return await _dbContextAsync.SaveChangesAsync();
        }

        public async Task<int> DeleteAsync(T entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");

            Entities.Remove(entity);

            return await _dbContextAsync.SaveChangesAsync();
        }
    }
}
